using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using FireStarter.Base;
using FireStarterModeller.BO;
using Habanero.Base.Exceptions;
using Habanero.BO;

namespace FireStarterModeller.Logic
{
    /// <summary>
    /// Creator for Creating a <see cref="UIFormInfo"/>
    /// based on certain heuristics e.g. Boolean map to check box. Dates to DT Pickers all 
    /// other types to Text Boxes.
    /// </summary>
    public class UIFormCreator
    {
        public UIField CreateUIField(DMProperty property)
        {
            if (property == null) throw new ArgumentNullException("property");
            if (property.PropertyType == null)
            {
                throw new HabaneroApplicationException("The property Type for '" + property.PropertyName + "' cannot be null in method 'UIFormCreator.GetControlType'");
            }
            
            ValidatePropertySetupCorrectly(property);
            UIField formField = new UIField
                        {
                            Property =  property,
                            PropertyName = property.PropertyName,
                            OrdinalPosition = property.OrdinalPosition,
                            UIControlType = GetControlType(property)
                        };
            return formField;
        }

        protected UIField CreateUIField(DMRelationship relationship)
        {
            if (relationship == null) throw new ArgumentNullException("relationship");

            UIField formField = new UIField { PropertyName =  relationship.RelationshipName };
            if (relationship.RelationshipProperties.Count > 0)
            {
                IDMProperty ownerProperty = relationship.RelationshipProperties[0].OwnerProperty;
                formField.OrdinalPosition = ownerProperty == null ? 0 : ownerProperty.OrdinalPosition;
            }
            else
            {
                formField.OrdinalPosition = 0;
            }
            
            formField.UIControlType = GetComboBoxControlType(relationship.OwnerClass.Solution);
            formField.UIControlMapperType = GetRelationshipControlMapperType(relationship.OwnerClass.Solution);
            return formField;
        }

        private static UIControlMapperType GetRelationshipControlMapperType(IDMSolution solution) {
            return ((DMSolution)solution).GetUIControlMapperType(BOBroker.GetMapperAssemblyName(), "AutoLoadingRelationshipComboBoxMapper");
        }



        private static void ValidatePropertySetupCorrectly(DMProperty property)
        {
            if (property.Class == null)
            {
                throw new HabaneroArgumentException
                    ("property.Class", "You cannot create a formField for a property that is not associated with a class (Property " + property.PropertyName + "'");
            }
            if (property.Class.Solution == null)
            {
                throw new HabaneroArgumentException
                    ("property.Class.Solution", "You cannot create a formField for a property that is not associated with a Solution - Property '" + property.PropertyName + "'");
            }
        }

        //Idea: This should be moved into some sort of a a mapper class? Brett 22 03 2009
        private static UIControlType GetControlType(IDMProperty property)
        {

            UIControlType type;
            if (property.HasLookupList)
            {
                type = GetComboBoxControlType(property.Class.Solution);
            }
            else
            {
                switch (property.PropertyType.PropertyTypeName)
                {
                    case "Boolean":
                        type = GetCheckBoxControlType(property.Class.Solution);
                        break;
                    case "DateTime":
                        type = GetDateTimeControlType(property.Class.Solution);
                        break;
                    default:
                        type = GetTextBoxControlType(property.Class.Solution);
                        break;
                }
            }
            return type;
        }

        private static UIControlType GetDateTimeControlType(IDMSolution solution)
        {
            return GetControlType(solution, "System.Windows.Forms", "DateTimePicker");
        }

        private static UIControlType GetComboBoxControlType(IDMSolution solution)
        {
            return GetControlType(solution, "System.Windows.Forms", "ComboBox");
        }
        private static UIControlType GetControlType(IDMSolution solution, string assemblyName, string formFieldTypeName)
        {
            return ((DMSolution)solution).GetUIFormFieldControlType(assemblyName, formFieldTypeName);
        }
        private static UIControlType GetTextBoxControlType(IDMSolution solution)
        {
            return GetControlType(solution, "System.Windows.Forms", "TextBox");
        }
        private static UIControlType GetCheckBoxControlType(IDMSolution solution)
        {
            return GetControlType(solution, "System.Windows.Forms", "CheckBox");
        }

        public UIFormInfo CreateUIForm(DMClass dmClass)
        {
            if (dmClass == null) throw new ArgumentNullException("dmClass");
            BusinessObjectCollection<DMProperty> properties = dmClass.Properties;
           
            UIColumnLayout columnLayout;
            UIFormInfo boEditor = CreateColumnLayout(out columnLayout);

            foreach (DMProperty property in properties)
            { 
//                if (property.IsPartOfObjectIdentity) continue;
                if (property.IsPartOfSingleRelationship()) continue;
                columnLayout.UIFields.Add(CreateUIField(property));
            }
           
            foreach (DMRelationship relationship in dmClass.OwnerRelationships)
            {
                if (relationship.Cardinality == Cardinality.Multiple) continue;
                columnLayout.UIFields.Add(CreateUIField(relationship));
            }
            return boEditor;
        }

        /// <summary>
        /// Creates a <see cref="UIFormInfo"/>
        /// </summary>
        /// <param name="dmClass"></param>
        /// <param name="selectedFormProps"></param>
        /// <returns></returns>
        public UIFormInfo CreateUIForm(DMClass dmClass,  IEnumerable<string> selectedFormProps)
        {
            if (dmClass == null) throw new ArgumentNullException("dmClass");
            if (selectedFormProps == null) throw new ArgumentNullException("selectedFormProps");

            UIColumnLayout columnLayout;
            UIFormInfo boEditor = CreateColumnLayout(out columnLayout);

            foreach (var selectedFormProp in selectedFormProps)
            {
                var property = dmClass.FindPropByName(selectedFormProp);
                columnLayout.UIFields.Add(CreateUIField(property));
            }
            return boEditor;
        }

        private UIFormInfo CreateColumnLayout(out UIColumnLayout columnLayout)
        {
            UIFormInfo boEditor = new UIFormInfo();
            UITab tab = boEditor.UITabs.CreateBusinessObject();
            tab.Name = "default";
            columnLayout = tab.UIColumnLayouts.CreateBusinessObject();
            columnLayout.UITab = tab;
            return boEditor;
        }
    }
}